package org.yray.tts.media;

import java.util.ArrayList;
import java.util.List;

public class MediaByteBuf {

    private int type;
    private List<MediaByte> list;
    public MediaByteBuf(int type)
    {
        this.list=new ArrayList<>();
        this.type=type;
    }

    public void add(MediaByte mediaByte)
    {
        list.add(mediaByte);
    }

    public byte[] combine(int mixLen)
    {
        byte[] mixBytes=new byte[mixLen];
        ByteBuf byteBuf=new ByteBuf();
        //每个mdeia切成两段，一段是用来混音的
        for(int i=0;i<list.size();i++)
        {
            MediaByte mediaByte=list.get(i);
            int begin=mediaByte.getBegin();
            int len=mediaByte.getEnd()-begin;
            //第一段特殊处理
            if(i==0)
            {
                //重新刷新begin,end
                begin=0;
                len=mediaByte.getEnd()-begin-mixLen;
                byteBuf.addBytes(mediaByte.getBytes(),begin,len);
                //缓存混音段
                System.arraycopy(mediaByte.getBytes(),mediaByte.getEnd()-mixLen,mixBytes,0,mixLen);
            }
            //与最后一段特殊处理
            else if(i==list.size()-1)
            {
                byte[] afterMix=type==711?mix(mixBytes,mediaByte):mix8k(mixBytes,mediaByte);
                byteBuf.addBytes(afterMix,0,mixLen);
                begin=mediaByte.getBegin()+mixLen;
                //重新刷新end
                len=mediaByte.getBytes().length-begin;
                byteBuf.addBytes(mediaByte.getBytes(),begin,len);
            }
            //中间段
            else {
                byte[] afterMix=type==711?mix(mixBytes,mediaByte):mix8k(mixBytes,mediaByte);
                byteBuf.addBytes(afterMix,0,mixLen);
                begin=mediaByte.getBegin()+mixLen;
                len=mediaByte.getEnd()-begin-mixLen;
                byteBuf.addBytes(mediaByte.getBytes(),begin,len);
                //缓存混音段
                System.arraycopy(mediaByte.getBytes(),mediaByte.getEnd()-mixLen,mixBytes,0,mixLen);
            }

        }

        return byteBuf.toBytesAlign();
    }
    public byte[] mix(byte[] mixBytes,MediaByte mediaByte)
    {
        byte[] result=new byte[mixBytes.length];
        for(int j=0;j<mixBytes.length;j++)
        {
            byte a=mediaByte.getBytes()[mediaByte.getBegin()+j];
            byte b=mixBytes[j];
            result[j]=  (byte)( a&b );
        }
        return result;
    }

    public byte[] mix8k(byte[] mixBytes,MediaByte mediaByte)
    {
        byte[] result=new byte[mixBytes.length];
        for(int j=0;j<mixBytes.length;j+=2)
        {
            short sample1 = (short)  ( ( mediaByte.getBytes()[mediaByte.getBegin()+j] & 0xff ) | ( mediaByte.getBytes()[mediaByte.getBegin()+j+1] ) << 8 ) ;
            short sample2 = (short)  ( ( mixBytes[j] & 0xff ) | ( mixBytes[j+1]  ) << 8 ) ;
            short sample=(short) (sample1+sample2);
            result[j]=(byte)(sample&0xff);
            result[j+1]=(byte)(sample>>8);
        }
        return result;
    }
}
